<template>
  <div class="table">
    <ElConfigProvider :locale="config.locale">
      <ElTable :data="data.list" :pagination="pagination" :border="border" v-loading="loading"
        @selection-change="handleSelectionChange" :row-key="(row) => row.id" border header-cell-class-name="header-row">
        <ElTableColumn v-if="needIndex" type="selection" width="55" :reserve-selection="true" align="center" />
        <ElTableColumn v-if="needSelection" type="index" label="序号" width="60" align="center" />
        <ElTableColumn v-for="item of columns" :key="item" :prop="item.prop" :label="item.label"
          :sortable="item.sortable" :width="item.width" :filters="item.filters" :filter-method="item.filterMethod">
          <template #default="slotScope">
            <slot :name="item.slotName" :data="slotScope.row" :prop="item.prop">
              <span :class="{ 'clickable': item.click }" @click="item.click && item.click(item.prop, slotScope)">
                {{ slotScope.row[item.prop] }}
              </span>
            </slot>
          </template>
        </ElTableColumn>
      </ElTable>
      <ElPagination class="pagination" v-if="needPage" v-model:current-page="pagination.current"
        v-model:page-size="pagination.pageSize" :page-sizes="pageSizes" :background="true" :layout="pageLayout"
        :total="data.total" @current-change="handleCurrentChange" @size-change="handleSizeChange" />
    </ElConfigProvider>
    <Http v-model="data" v-model:loading="loading" ref="httpRef" :url="url" :method="method" :params="finalParams"
      :auto="auto" :concurrent="concurrent">
    </Http>
  </div>
</template>

<script lang="ts" setup>
import { computed, ref } from 'vue';
import { ElTable, ElTableColumn, ElPagination, ElConfigProvider } from 'element-plus';
import config from '../../config';
import Http from '@/components/Http';
import 'element-plus/dist/index.css'
import writeXlsxFile from "write-excel-file";

const props = defineProps({
  url: {
    type: String,
    default: ''
  },
  method: {
    type: String,
    default: 'get'
  },
  params: {
    type: Object,
    default: () => { return {} }
  },
  columns: {
    type: Array,
    default: () => []
  },
  border: {
    type: Boolean,
    default: true
  },
  //是否当参数变化时自动发送请求
  auto: {
    type: Boolean,
    default: false
  },
  //为true时允许出现并发请求
  concurrent: {
    type: Boolean,
    default: true
  },
  needIndex: {
    type: Boolean,
    default: true
  },
  needSelection: {
    type: Boolean,
    default: true
  },
  needPage: {
    type: Boolean,
    default: true
  },
  pageSizes: {
    type: Array,
    default: [10, 20, 50, 100]
  },
  pageLayout: {
    type: String,
    default: 'total, sizes, prev, pager, next, jumper'
  },
});
const emit = defineEmits(["onChange", "onSelectChange"]);
const data = ref({ list: [], total: 1 });
const loading = ref(false);
const httpRef = ref();
const pagination = ref({
  current: 1,
  pageSize: props.pageSizes[0],
});

const finalParams = computed(() => {
  return {
    ...props.params,
    page: pagination.value.current - 1,
    pageSize: pagination.value.pageSize
  }
})

function handleSizeChange() {
  send();
}
function handleCurrentChange() {
  send();
}

function handleSelectionChange(values) {
  emit('onSelectChange', values);
}

function send() {
  httpRef.value.send();
}

function toXlsx(filename) {
  const rows = [];
  const HEADER_ROW = props.columns.map((r) => {
    return {
      value: r.label,
      fontWeight: 'bold',
      backgroundColor: '#f5f7fa'
    }
  });
  rows.push(HEADER_ROW);
  for (const item of data.value.list) {
    const DATA_ROW = [];
    for (let index = 0; index < props.columns.length; index++) {
      DATA_ROW.push({
        type: String,
        value: item[props.columns[index].prop]
      })
    }
    rows.push(DATA_ROW);
  }
  writeXlsxFile(rows, {
    fileName: filename + '.xlsx'
  })
}

defineExpose({
  data,
  send,
  toXlsx
})

</script>
<style scoped>
:deep(.header-row) {
  background-color: #f5f7fa !important;
}

.clickable {
  cursor: pointer;
  color: blue;
}

.pagination {
  margin-top: 20px;
  display: flex;
  justify-content: end;
}
</style>